package com.mapbased.wfw;

import java.io.*;

import org.dom4j.*;
import java.util.Map;

/**
 *
 * <p>Title: </p>
 *
 * <p>Description: </p>
 * Init order:
 * 1.new instance
 * 2.set locale
 * 3.set headString
 * 4.parseXML
 * 5.set segments if parseXML by pageloder
 *
 * <p>Copyright: Copyright (c) 2004</p>
 *
 * <p>Company: mapbased.com</p>
 *
 * @author chy_hs(Baily)
 * @version 1.0
 *
 */

public abstract class Component
{
    public static final Object[] EMPTYSEGS=new Object[0];
    /**
     * set from pageLoder
     */
    protected String locale=null;
    //  public static final String ComponentName="null";
    protected Object[] segments=EMPTYSEGS;
    //   protected Component[] children;
   // protected String headString;
    protected Object [] headSegments=null;
    public boolean isHeadable()
    {
        return headSegments != null;
    }

    public abstract void renderHeader(RenderContext context,StringBuffer sb,
                                      Map m);

    abstract public void render(RenderContext context)
        throws IOException;

    /**
     * a component can choose to parse an element or not.
     * generally, component fetch the attributes it needed and delete the attribute
     * then return the element to pageloader ,let pageloader parse the element
     * also, the component can also parse the component into segments by call the pageloader
     * and return null
     * @param ele Element
     * @param loader PageLoader
     * @return Element or null:if wanna page loader parse the component,return the ele,
     * else return null
     */
    abstract public Element parseXml(Element ele,com.mapbased.wfw.PageLoader.LoadContext
                                    lc);


    protected static final String fetchAttribute(Element e,String attribtueName, String defaultValue)
    {
     Attribute a=   e.attribute(attribtueName);
     if(a==null)
     {
         return defaultValue;
     }

     String s=a.getValue();

     e.remove(a);

     return s;

    }


    /**
     * whether the shell element is include
     * @return boolean
     *
     * always include the shell ,if is border ,use a template
         public boolean includeShell()
         {
        return true;
         }*/

    /**
     * render the bingingvalues to the string buffer
     * @param rc RenderContext
     * @param segments Object[]
     * @param w StringBuffer
     */

    public static final void renderBinding(RenderContext rc,
        Object[] segments,StringBuffer w)
    {

          for(int i=0;i < segments.length;i++)
          {
              Object o=segments[i];

              if(o instanceof String)
              {
                  w.append((String)o);

              }

              else if(o instanceof Binding)
              {
                  Object ro=((Binding)o).getValue(rc);
                  if(ro != null)
                  {
                      w.append(String.valueOf(ro));
                  }
              }
              else
              {
                  throw new java.lang.RuntimeException("known segments type:" + o);
              }

          }


    }




    public static final void defalutRenderBehavior(RenderContext context,
        Object[] segments)
        throws IOException
    {
           Writer w=context.getOutputWriter();
        for(int i=0;i < segments.length;i++)
        {
            Object o=segments[i];

            if(o instanceof String)
            {
                w.write((String)o);

            }
            else if(o instanceof Component)
            {
                ((Component)o).render(context);
            }
            else if(o instanceof Binding)
            {
                Object ro=((Binding)o).getValue(context);
                if(ro != null)
                {
                    w.write(String.valueOf(ro));
                }
            }
            else
            {
                throw new java.lang.RuntimeException("known segments type:" + o);
            }

        }

    }

    final public void defalutRenderBehavior(RenderContext context)
        throws IOException
    {
        defalutRenderBehavior(context,this.segments);
    }

    public void setSegments(Object[] segments)
    {
        this.segments=segments;
    }

    public Object[] getSegments()
    {
        return segments;
    }

}
